package com.bw.medical.realtime.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bw.medical.realtime.common.MedicalCommon;
import io.lettuce.core.RedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulRedisConnection;
import io.lettuce.core.api.async.RedisAsyncCommands;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class RedisUtil {

    private static final JedisPool pool;

    static {

        GenericObjectPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(300);  // 最多提供 300 个连接
        config.setMaxIdle(10);  // 最多允许 2 个空闲连接
        config.setMinIdle(2); // 最少允许 2 个空闲连接
        config.setMaxWaitMillis(10 * 1000);  // 获取连接最多等到时间
        config.setTestOnCreate(true);
        config.setTestOnBorrow(true);
        config.setTestOnReturn(true);

        pool = new JedisPool(config, MedicalCommon.REDIS_HOST, MedicalCommon.REDIS_PORT);
    }

    public static Jedis getRedisClient() {
        // 1. 直接 new
        // 2. 使用连接池
        Jedis jedis = pool.getResource();
        jedis.select(4);  // 选择单独的库
        return jedis;
    }

    /**
     * 获取一个到 redis 线程安全的异步连接, key value 都用 utf-8 进行编码
     *
     * @return
     */
    public static StatefulRedisConnection<String, String> getAsyncRedisConnection() {
        // 连接到 redis 的 0号库
        RedisClient redisClient = RedisClient.create("redis://" + MedicalCommon.REDIS_HOST + ":" + MedicalCommon.REDIS_PORT + "/0");

        return redisClient.connect();
    }

    /**
     * 异步的方式读取维度
     *
     * @param asyncConn 到 redis 的异步连接
     * @param key       要读取的 key
     * @return 读取到的维度数据, 如果是 null,表示没有读到维度数据
     */
    public static JSONObject asyncReadDim(StatefulRedisConnection<String, String> asyncConn, String key) {
        RedisAsyncCommands<String, String> asyncCommon = asyncConn.async();
        try {
            String json = asyncCommon.get(key).get();
            if (json != null) {
                return JSON.parseObject(json);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 异步的方式写维度数据到 redis 中
     *
     * @param asyncConn 异步连接
     * @param key       写入的 key
     * @param dim       要写入的具体维度数据
     * @return 写入成功失败的简单描述: ok 或
     */
    public static String asyncWriteDim(StatefulRedisConnection<String, String> asyncConn,
                                       String key,
                                       JSONObject dim) {
        RedisAsyncCommands<String, String> asyncCommands = asyncConn.async();
        RedisFuture<String> future = asyncCommands.setex(key, 2 * 24 * 60 * 60, dim.toJSONString());
        try {
            return future.get();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
